// 进程事件循环
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <string.h>
#include <signal.h>   //信号相关头文件 
#include <errno.h>    //errno
#include <unistd.h>

#include "global.h"
#include "conf.h"
#include "log.h"
#include "net/netglobal.h"


// 只用于本文件的函数声明
static void Work_process_cycle();// 无限循环(处理网络事件和定时器事件以对外提供web服务)
static void Work_process_init();// 进程开始处理事件前的一些初始化(线程池、套接字、epoll)

/**
 * 开启主进程主循环函数
 */
void Master_process_cycle(){
    // 开启信号屏蔽，一些初始化过程中不希望收到这些信号的干扰
    sigset_t set;// 信号集
    sigemptyset(&set);// 清空信号集
    // ---------------------信号屏蔽开启-----------------------
    sigaddset(&set, SIGCHLD);// 子进程状态改变
    sigaddset(&set, SIGALRM);// 定时器超时
    sigaddset(&set, SIGIO);// 异步I/O
    sigaddset(&set, SIGINT);// 终端中断符
    sigaddset(&set, SIGHUP);// 连接断开
    sigaddset(&set, SIGUSR1);// 用户定义信号
    sigaddset(&set, SIGUSR2);// 用户定义信号
    sigaddset(&set, SIGWINCH);// 终端窗口大小改变
    sigaddset(&set, SIGTERM);// 终止
    sigaddset(&set, SIGQUIT);// 终端退出符
    // 设置阻塞（如果期间收到这些信号，系统会收集起来，放开后再接收）
    if (sigprocmask(SIG_BLOCK, &set, NULL) == -1){
        Log_Error(errno, "初始化前开启信号屏蔽失败!"); // 即使失败也继续程序，不退出了
    }
    // 进程开始处理事件前的一些初始化(线程池、套接字、epoll)
    Work_process_init();
    if (sigprocmask(SIG_UNBLOCK, &set, NULL) == -1) {
        Log_Error(errno, "初始化后结束信号屏蔽失败!");
    }
    // ---------------------信号屏蔽结束-----------------------

    Work_process_cycle();// 进入工作循环
}

/**
 * 工作循环（处理网络事件和定时器事件以对外提供web服务）
 */
static void Work_process_cycle(){
    Log_Info(0,"开始进入事件处理循环........!");

    // 进入功能处理循环
    for( ; ; ) {
        if(g_stopEvent == 1) break;// 如果系统关闭了就退出循环
        Process_events_and_timers();// 处理网络事件和定时器事件s
    }

    // 如果从循环出来了，说明系统结束了(不管是异常还是不异常)
    g_threadpool.StopAll();// 停止自身的线程池
    g_socket.Shutdown_subproc();// 释放线程资源、各种队列资源
}

/**
 * 处理事件循环前的一些初始化工作函数(线程池、套接字、epoll)
 */
static void Work_process_init(){
    // (此时仍然屏蔽了一些信号，避免打扰)

    // 初始化线程池代码，需要先创建（至少比socket相关先）
    CConfig *p_config = CConfig::GetInstance();
    int tmpthreadnums = p_config->GetIntDefault("net_ProcMsgRecvWorkThreadCount",5);
    if(g_threadpool.Create(tmpthreadnums) == false){
        exit(-2);// 创建失败直接退出，即使内存没释放也没关系
    }

    sleep(1);// 休息1秒缓一下

    // 初始化一些互斥量、信号量和线程函数
    if(g_socket.Initialize_subproc() == false){
        exit(-2);// 创建失败直接退出，即使内存没释放也没关系
    }

    // 初始化Epoll相关内容
    g_socket.Epoll_init();
}